home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TPUG - Toronto PET Users Group
/
TPUG Users Group CD
/
TPUG Users Group CD.iso
/
CRS
/
crs49.d81
/
hack2-2.sfx
/
hack.2
Wrap
Text File
|
1990-02-12
|
47KB
|
1,000 lines
┼ND;
╫RITELN;
╫RITELN ('╩OB ├OMPLETED :-)');
END;
╞OR ├OUNTER := 1 TO 3 DO
╫RITELN;
█ ═AKE A BIT OF SPACE WHEN FINISHED :-) ▌
END.
================================================================================
┬┴╬╦╔╬╟ ╧╬ ╟┼╧╙
BY ╥OBERT ┴. ╦NOP ╩R.
╔. ╔NTRODUCTION
╟┼╧╙ WAS ORIGINALLY WRITTEN FOR THE ├OMMODORE 64. ╫HEN ┬ERKELEY ╙OFTWORKS
CAME OUT WITH ╟┼╧╙128 (AND, FOR A TIME, IT WASN'T CLEAR THAT THEY WOULD; THEN,
IT LOOKED LIKE THEY WOULD RELEASE A ╟┼╧╙128 THAT WOULDN'T SUPPORT THE 80
COLUMN SCREEN; FINALLY, THE RELEASE OF ╟┼╧╙128 DID TURN OUT TO BE A FULL 128
PROGRAM), IT WAS LARGELY COMPATIBLE WITH ╟┼╧╙64. ┴PPLICATIONS COULD SHARE
DOCUMENTS (A GEO╨AINT FILE IS A GEO╨AINT FILE), AND EVEN MANY ╟┼╧╙64
APPLIATIONS RUN ON THE 128 IN 40 COLUMNS. ╘HIS HERITAGE IS ALSO EVIDENT TO
THE ╟┼╧╙ PROGRAMMER.
┴S WE ALL KNOW, THE ├-128 HAS TWO 64╦ ╥┴═ BANKS; THE ├-64 ONLY HAS ONE 64╦ ╥┴═
"BANK." ╘HUS, OF COURSE, ALL OF ╟┼╧╙64 GOES INTO THAT ONE 64╦ ╥┴═ SPACE.
╘HIS INCLUDES THE ╦ERNAL AS WELL AS THE SPACE AVAILABLE TO APPLICATIONS. ╧NCE
THE ╦ERNAL, GRAPHICS SCREENS, AND SO FORTH, HAVE CLAIMED THEIR ╥┴═, THE ╟┼╧╙
PROGRAMMER IS LEFT WITH 23.75╦ OF MEMORY FROM $0400 TO $5FFF.
╘O A CURSORY "GLANCE," THE ╟┼╧╙128 PROGRAMMING ENVIRONMENT LOOKS VERY MUCH
LIKE THE ╟┼╧╙64 PROGRAMMING ENVIROMENT. ┘OU STILL HAVE $0400 TO $5FFF
AVAILABLE FOR APPLICATIONS; GRAPHICS SCREENS AND VARIABLES ARE IN THE SAME
PLACE; THE ╦ERNAL JUMP TABLE IS THE SAME (WITH SOME 128 SPECIFIC ADDITIONS).
╫HAT HAPPENED TO THE OTHER 64╦ THAT THE 128 HAS AVAILABLE?
┴S IT TURNS OUT, THE CORE OF ╟┼╧╙128- INCLUDING THE APPLICATION PROGRAM SPACE,
THE 40 COLUMN FOREGROUND AND BACKGROUND SCREEN, AND THE ╦ERNAL JUMP TABLE- ARE
ALL IN THE 128'S ╥┴═ BLOCK 1, WHAT ╟┼╧╙ CALLS ╞RONT╥┴═. ╘O US 128 PROGRAMMERS
USED TO ╥┴═ BLOCK 0 BEING THE "MAIN" ╥┴═ BLOCK, THIS MAY SOUND ODD. ╚OWEVER,
IT ACTUALLY MAKES SENSE. ╞IRST OF ALL, SINCE ╟┼╧╙ IS AN OPERATING SYSTEM IN
AND OF ITSELF, AND APPLICATIONS ALMOST NEVER NEED TO CALL THE ├128'S ╦ERNAL
ROUTINES, THE APPLICATION NO LONGER NEEDS ACCESS TO ┬ANK 15. ╙ECOND, IT
ALLOWS ╟┼╧╙128 TO KEEP MUCH OF ITS MEMORY MAP THE SAME AS ╟┼╧╙64; IT CAN USE
THE MEMORY RANGE FROM $200-$3FF IN ╥┴═ 1 WITHOUT WORRYING ABOUT DISTURBING KEY
SYSTEM ROUTINS LIKE ╙╘┴╞┴╥ WHICH ARE IN THE SAME MEMORY RANGE IN ╥┴═ 0.
╔╔. ┘EAH, ┘EAH, ┬UT ╫HAT ╚APPENED TO ╥┴═ 0 ┴NYWAY?
╔T'S STILL THERE. ╙OME OF ╥┴═ 0 IS USED BY ╟┼╧╙128 TO IMPROVE THE SYSTEM
PERFORMANCE AND TO TAKE ADVANTAGE OF THE 128'S UNIQUE FEATURES. (╞OR
INSTANCE, THE CODE FOR THE "SOFTWARE SPRITES" SEE ON THE 128'S 80 COLUMN
SCREEN IS FOUND BENEATH $2000 IN ╥┴═ 0.) ╞ORTUNATELY, SOME SPACE DOES REMAIN
AVAILABLE FOR AN APPLICATION TO USE. ╔N ╥┴═ 0, THE 32╦ MEMORY SPACE BETWEEN
$2000 AND $9FFF IS NOT NORMALLY USED BY ╟┼╧╙, AND IS ┴╠═╧╙╘ AVAILABLE FOR
APPLICATION USE [1].
╫HY DO ╔ SAY "ALMOST"? ╘HE PROBLEM IS DESK ACCESSORIES. ╫HEN ╟┼╧╙ 64 LOADS A
DESK ACCESSORY (─┴), IT MUST LOAD IT INTO THE SAME APPLICATION SPACE AS THE
APPLICATION LOADING THE ─┴. ╘HE MEMORY THAT THE ─┴ WILL USED IS FIRST SAVED
TO DISK IN A SWAP FILE. ╒NDER ╟┼╧╙128, THE ROUTINE ╠D─ESK┴CC, INSTEAD OF
SAVING A SWAP FILE TO DISK, COPIES THE MEMORY TO BE OVERWRITTEN BY THE ─┴ TO
╥┴═0 BETWEEN $2000 AND $9FFF. ╙O, IF YOUR APPLICATION USES ─┴'S (AND IT IS
HIGHLY RECOMMENDED THAT MAJOR APPLICATIONS SUPPORT ─┴'S), YOU HAVE TO BE
CAREFUL USING THE SPACE BETWEEN $2000 AND $9FFF. ┘OU CAN USE IT AS TEMPORARY
SWAP SPACE WITHIN ROUTINES- BUT YOU CANNOT ASSUME THAT IT WILL REMAIN INTACT
WHENEVER YOUR ROUTINE RETURNS TO THE ╟┼╧╙ ═AIN╠OOP WITH YOUR APPLICATION IN A
STATE THAT WILL ALLOW THE LOADING OF ─┴'S.
╬OWADAYS, ╥┴═ 0 IS NOT THE BE-ALL AND END-ALL. ╟┼╧╙128 WAS WRITTEN FOR THE
├=128, NOT THE ├=256. ├ONSEQUENTLY, IF YOU HAVE EXPANDED YOUR 128 TO 256╦ OR
512╦ AS DESCRIBED IN THE ARTICLES BY ╥ICHARD ├URCIO IN ╘WIN ├ITIES 128 ╔SSUES
#30 AND #31 [2,3], YOU HAVE FREE USE OF ╥┴═ 2-3 (256╦) OR ╥┴═ 2-7 (512╦).
(╬OTE THAT YOU SHOULD NOT TOUCH ╥┴═ 4-7 ON A 512╦ 128 IF YOU WANT TO BE
COMPATIBLE WITH TASK SWITCHING AS DESCRIBED IN ╘├128 #31. ┴LSO, ALTHOUGH ╟┼╧╙
RIGHT NOW DOES NOT RUN IN THE 2ND 256╦, APPLICATIONS SHOULD NOT ASSUME THEY
ARE IN THE 1ST 256╦, AND THUS SHOULD BE CAREFUL WITH THE 512╦ MODE BITS (4-5)
IN THE ══╒ ╥AM ├ONFIGURATION ╥EGISTER (╥├╥), $D506.) ╫HILE THE NUMBER OF
PEOPLE WITH 256╦ AND 512╦ 128'S IS NOW SMALL, YOU CAN BE SURE THAT IT WILL
INCREASE WHEN THE PROMISED ┌╔╨ ACCELERATOR BOARD FOR THE 128 COMES OUT; THE
CURRENT SPECS FOR THE ┌╔╨ BOARD INCLUDE PROVISIONS FOR MEMORY EXPANSION ON THE
BOARD.
╥┴═ 2-3 PROVIDE ALMOST ANOTHER COMPLETE 128╦ AVAILABLE FOR YOUR APPLICATION TO
USE. ╙O HOW DO YOU GO ABOUT ACCESSING THIS?
╔╔╔. ╙TORING ─ATA ╔N ╧THER ╥┴═ ┬LOCKS
╘HE MOST OBVIOUS USE FOR ╥┴═ BLOCKS OTHER THAN ╞RONT╥┴═ (WHICH IS THE ONLY
BLOCK WHERE ╟┼╧╙ ╦ERNAL ROUTINES ARE AVAILABLE) IS AS DATA STORAGE. ╞OR
INSTANCE, ONE COULD VISUALIZE A GEO╨AINT PREVIEWING UTILITY WHICH LOADS AND
DECOMPACTS AN ENTIRE GEO╨AINT DOCUMENT AT ONCE TO ╥┴═ 2. (╘HE FULL
DECOMPACTED GEO╨AINT DOCUMENT WOULD REQIRE 56.25╦.) ╧NE COULD THEN QUICKLY
SCROLL THROUGH THE DOCUMENT BY JUST COPYING THE RELEVANT PORTIONS OF THE
BITMAP FROM ╥┴═ 2 TO THE FOREGROUND SCREEN. ╧R, IF ONE WERE REALLY BOLD, ONE
COULD JUST REDIRECT THE ╓╔├ SCREEN MEMORY TO THE RELEVANT RANGE IN ╥┴═2 USING
THE PROPER ══╒ AND ╓╔├ REGISTERS. (╘HIS WOULD ACTULLY REQUIRE USE OF BOTH ╥┴═
2 AND 3, SINCE ╓╔├ SCREEN LOCATIONS ARE QUANTIZED TO 8╦; YOU LOSE THE USE OF
THE HIGHEST 8╦, SINCE YOU DON'T WANT TO OVERWRITE THE ══╒ REGISTERS AT
$FF00-$FF05; ADDITIONAL PRACTICAL CONSIDERATIONS MAKE USE OF THE LOWEST 8╦
DIFFICULT.)
╟┼╧╙128 PROVIDES A FEW ROUTINES FOR EASILY MOVING DATA BETWEEN ╞RONT╥┴═ AND
WHAT IT CALLS ┬ACK╥┴═ (BUT WE KNOW IT JUST MEANS ╥┴═ 0). ╚APPILY, THESE
ROUTINES WORK QUITE ADMIRABLY WITH ╥┴═ 2 AND 3. (╘O ACCESS ╥┴═ 4-7, FIDDLE
BITS 4 AND 5 OF THE ══╒ ╥├╥ TO MAKE THE DESIRED ╥┴═ BLOCKS APPEAR TO THE
SYSTEM AS VIRTUAL ╥┴═ 2 AND ╥┴═ 3, THEN CALL THESE ROUTINES.) ╘HE CORE
ROUTINE IS ─O┬╧P, WHICH IS SUMMARIZED BELOW [4]:
***********************************************************************
─O┬╧P=$C2EC: ├OPY/VERIFY MEMORY BETWEEN ╥┴═ BLOCKS ON THE ├-128.
╨ASS:
R0 : ┴──╥1 - ADDRESS OF FIRST ("SOURCE") MEMORY RANGE
R1 : ┴──╥2 - ADDRESS OF SECOND ("DESTINATION") MEMORY RANGE
R2 : ├╧╒╬╘ - NUMBER OF BYTES TO OPERATE ON
R3╠ : ┴1┬┴╬╦ - BANK OF ┴──╥1 (E.G. 1=╞RONT╥┴═, 0=┬ACK╥┴═)
R3╚ : ┴2┬┴╬╦ - BANK OF ┴──╥2
Y : ═╧─┼ - OPERATION TO PERFORM
╥ETURNS: R0-R3 UNCHANGED
WHEN VERIFYING: X=$00 IF TWO RANGES MATCH, X=$FF IF THEY DON'T MATCH
─ESTROYS: A,X,Y
╘HE OPERATION MODE IS PASSED IN Y AS FOLLOWS:
BIT0 BIT1 ─ESCRIPTION
---- ---- -----------
0 0 ═OVE FROM MEMORY AT ┴──╥1 TO MEMORY AT ┴──╥2
0 1 ═OVE FROM MEMORY AT ┴──╥2 TO MEMORY AT ┴──╥1
1 0 ╙WAP MEMORY AT ┴──╥1 AND ┴──╥2
1 1 ╓ERIFY (COMPARE) MEMORY AT ┴──╥1 AND ┴──╥2
***********************************************************************
(R0, R1, ETC. ARE ALL THE STANDARD ┬╙╫ SYMBOLS DEFINED IN THE ╧FFICIAL ╟┼╧╙
╨ROGRAMMER'S ╥EFERENCE ╟UIDE [5], AND THAT COME IN THE FILE GEOS╙YM WITH
GEO╨ROGRAMMER.)
╘HERE ARE A NUMBER OF ADDITIONAL ROUTINES WHICH ARE ALSO PROVIDED FOR
PROGRAMMER CONVENIENCE WHICH AUTOMATICALLY SET THE ═╧─┼ IN THE Y REGISTER FOR
YOU. ╔N ALL OF THESE ROUTINES, R0-R3 HAVE THE SAME MEANING AS THEY DO IN
─O┬╧P.
╥OUTINE ┴DDRESS ═╧─┼ ─ESCRIPTION
------- ------- ---- -----------
═OVE┬─ATA $C2E3 00 ├OPY DATA AT ┴──╥1 TO ┴──╥2
╙WAP┬─ATA $C2E6 10 ╙WAP DATA BETWEEN ┴──╥1 AND ┴──╥2
╓ERIFY┬─ATA $C2E9 11 ├OMPARE DATA AT ┴──╥1 AND ┴──╥2
╔ HAVE WRITTEN A SHORT DEMONSTRATION PROGRAM WHICH SHOWS THE USE OF ═OVE┬─ATA
AND ╓ERIFY┬─ATA. ╘HE FULL SOURCE TO THIS PROGRAM, ┬═OVER, IS AVAILABLE
THROUGH ANONYMOUS FTP AT TYBALT.CALTECH.EDU (IN THE RKNOP/HACKING.MAG
DIRECTORY) AS WELL AS ELSEWHERE. ╔F YOU CAN'T FIND IT, CONTACT ME (ADDRESSES
ARE BELOW). ╘HE SOURCE IS GEO╨ROGRAMMER CODE, IN GEO╫RITE 2.1 FORMAT. ┴LL OF
THE FILES YOU NEED (EXCEPT GEOS╙YM AND GEOS═AC, WHICH COME WITH GEO╨ROGRAMMER)
ARE IN THE BMOVER.SFX ARCHIVE.
╘HE FIRST FUNCTION OF ┬═OVER REPEATEDLY COPIES A SINGLE BLOCK ON ╥┴═ 1 TO
SUCCESSIVE PARTS IN MEMORY IN ANY OTHER SPECIFIED BANK. ╘HE DESTINATION BANK,
DESTINATION ADDRESSES, SIZE OF THE BLOCK TO MOVE, AND NUMBER OF TIMES TO COPY
IT ARE ALL SET IN CONSTANTS FOUND AT THE BEGINNING OF THE SOURCE FILE ┬═OV┴SM.
╧NCE THE MOVES (WHICH USE ═OVE┬─ATA) HAVE ALL BEEN PERFORMED, ┬═OVER USES
╓ERIFY┬─ATA TO MAKE SURE THAT ALL OF THE BLOCKS WERE COPIED SUCCESFULLY.
╞OR INFORMATIONAL PURPOSES, ┬═OVER REPORTS THE AMOUNT OF TIME (IN TENTHS OF
SECONDS) IT TOOK TO PERFORM ALL OF THE MOVES. (╞OR THIS, ╔ USE THE ├╔┴ #1 ╘╧─
CLOCK, SAVING ITS VALUE AT THE BEGINNING AND END OF THE MOVE, AND SUBTRACTING
TO GET THE DIFFERENCE.) ╔ RAN A TRIAL WHERE ╔ COPIED AN 8╦ BLOCK OF MEMORY TO
╥┴═ 2 7 TIMES (THUS FILLING 56╦ OF ╥┴═ 2). ╘HESE MOVES TOGETHER TOOK 1 SECOND
AT 2 ═╚Z, AND 2.2 SECONDS AT 1 ═HZ. 56╦/SECOND MAY BE NO ─═┴, BUT IT'S FASTER
THAN A BURST LOAD!
╔╓. ┼XECUTING ╥OUTINES ╔N ╧THER ┬ANKS
╙O, YOU'VE WRITTEN AN OBJECT ORIENTED DRAWING PROGRAM THAT STORES ITS LIST OF
OBJECTS (32 BYTE RECORDS) IN ╥┴═ 2. ╧R, YOU HAVE A DATABASE THAT HAS RECORDS
IN ╥┴═ 0. ┘OU WANT TO DELETE ONE RECORD AT THE BEGINNING OF THE LIST, WHICH
MEANS MOVING ALL OF THE SUBSEQUENT RECORDS DOWN OVER THE MEMORY FREED UP BY
THE DELETION. ╘HERE ARE A FEW THINGS YOU CAN DO. ╧NE, YOU CAN USE ├RAIG
┬RUCE'S DYNAMIC MEMORY ALLOCATION ROUTINES (HIGHLY RECOMMENDED). ╘WO, YOU CAN
REPEATED DO ═OVE┬─ATA TO MOVE MEMORY FROM ╥┴═ 2 (OR 0) TO A BUFFER IN ╞RONT╥┴═
AND BACK. ╧R, YOU CAN WRITE A SHORT MOVER ROUTINE IN THE ╥┴═ BANK WHERE ALL
THE MOVING IS GOING TO HAPPEN.
╘HIS IS JUST AN EXAMPLE. ╧NE CAN VISUALIZE OTHER REASONS FOR CALLING ROUTINES
IN OTHER ╥┴═ BANKS (WHAT ╔ CALL "EXTRABANKAL ROUTINES"). ╘HERE EXIST NO ╟┼╧╙
╦ERNAL ROUTINES FOR CALLING EXTRABANKAL ROUTINES. ┴DDITIONALLY, SINCE YOUR
MAIN APPLICATION MEMORY IS IN ╥┴═ 1, YOU ARE INABLE TO USE THE 128 ╦ERNAL'S
╩╙╥╞┴╥ (WHICH RETURNS YOU TO ┬ANK 15). ╙O, WE ARE LEFT WITH IMPLEMENTING OUR
OWN ╩╙╥╞┴╥.
╟┼╧╙128 NORMALLY OPERATES WITH ╬╧ COMMON MEMORY ENABLED. ╘HANKS TO ONE OF THE
LESS WELL-KNOWN FEATURES OF THE ══╒, THERE IS NO NEED TO ENABLE COMMON MEMORY.
╘HE ══╒ ZERO PAGE REGISTERS ($D507 AND $D508) ALLOW YOU TO LOCATE THE ZERO
PAGE THAT THE PROCESSOR SEES ANYWHERE IN ╥┴═ 0 OR ╥┴═ 1. ╫HAT THIS MEANS IS,
NO MATTER WHAT YOUR MEMORY CONFIGURATION IS, THE PROCESSOR SEES ZERO PAGE IN
THE ╥┴═ BLOCK SPECIFIED IN $D508. (╒NLESS YOU HAVE COMMON MEMORY ENABLE, IN
WHICH CASE IT IS NOT A GOOD IDEA TO PUT ┌╨ IN ╥┴═ BLOCKS OTHER THAN ╥┴═ 0
[6,7].) ╙O, ZERO PAGE IS EFFECTIVELY COMMON MEMORY!
╘HIS PROVIDES FOR THE POSSIBLITY OF COPYING TO ZERO PAGE A SHORT "SWITCHBOARD"
ROUTINE, BASICALLY A REIMPLEMENTATION OF ╩╙╥╞┴╥, WHICH CONFIGURES THE SYSTEM
FOR THE DESTINATION BANK, JSR'S TO A ROUTINE, RECONFIGURES THE SYSTEM FOR THE
CALLING BANK, AND RTS'S.
╔ ALSO DEMONSTRATE THIS TECHNIQUE IN ┬═OVER. ╘HE SECOND FUNCTION OF ┬═OVER
FIRST USES ═OVE┬─ATA TO COPY A ROUTINE TO $2000 IN ─┼╙╘┬┴╬╦ (WHICH IS SET
RIGHT NOW IN THE SOURCE CODE TO ╥┴═ 0). ╔T THEN COPIES THE ROUTINE ┌╨╩╙╥ TO
$02, WHICH STORES ─┼╙╘├╞╟ IN $FF00 AND JSR'S TO $2000. ╘HE ROUTINE AT $2000
MOVES SOME DATA AROUND IN ─┼╙╘┬┴╬╦. ╧NCE ┌╨╩╙╥ HAS RETURNED THE PROGRAM FLOW
TO ╞RONT╥┴═, ┬═OVER CALLS ╓ERIFY┬─ATA TO MAKE SURE EVERYTHING WORKED.
╫HILE MESSING AROUND IN DIFFERENT BANKS, TO BE SAFE ╔ DISSABLE ╔╥╤ INTERRUPTS.
╧N A RELATED NOTE, GEO─EBUGGER 2.0 SEEMS TO HAVE PROBLEMS WITH PROGRAMS
MESSING AROUND WITH DIFFERENT BANKS. ╔T IS NOT SURPRISING THAT THE ┬ACK╥┴═
DEBUGGER (WHICH LOCATES ITSELF IN ╥┴═ 0) WOULD HAVE TROUBLE WITH PROGRAMS THAT
TRIED TO USE ╥┴═ 0, BUT IT ALSO HAS TROUBLE WITH PROGRAMS THAT TRY TO USE ╥┴═
2 AND 3. ╘HIS IS TRUE EVEN WHEN ONE USES THE SYSTEM ROUTINE ═OVE┬─ATA. (╔
FOUND THAT ╔ WAS SOMETIMES ABLE TO MAKE IT PAST A CALL TO ═OVE┬─ATA WHILE IN
THE DEBUGGER, BUT THAT MORE OFTEN THE SYSTEM WOULD HANG. ╘HIS IS ALL PROBABLY
AN INTERRUPT-RELATED ISSUE.)
╔F ONE IS TO BE REALLY CLASSY, ONE DOESN'T ACTUALLY HAVE TO COPY THE ┌╨╩╙╥
ROUTINE TO ZERO PAGE. ╧NE COULD ASSEMBLE THE APPLICATION SUCH THAT ┌╨╩╙╥ FELL
TO A KNOWN OFFSET FROM A PAGE BOUNDRY; THEN, USE THE ══╒ TO POINT ZERO PAGE TO
THE PAGE CONTAING ┌╨╩╙╥. ╒NFORTUNATELY, THIS TECHNIQUE DID NOT WORK ON MY
512╦ EXPANDED 128. ╘HE ONE INCOMPATILITY ╔ HAVE FOUND IS THAT WITH THE 512╦
MODIFICATION ENABLED (╔ DO HAVE A SWITCH TO DISABLE IT, DON'T WORRY), THE ══╒
FAILS TO CORRECTLY SEE ZERO PAGE IN ╥┴═ 1 WHEN REQUESTED TO. ╥ICHARD ├URCIO
EXPERIMENTED WITH IT, AND IT SEEMS THAT WHEN YOU TRY TO RELOCATE ZERO PAGE TO
A PAGE IN ╥┴═ 1, IT IS ACTUALLY SEEN IN ╥┴═ 3. ╔T IS NOT YET CLEAR WHETHER
THIS IS A PROBLEM WITH THE 256╦/512╦ MODIFICATION, OR IF THE ══╒ IN A STOCK
128 JUST RELOCATES ┌╨ TO ╥┴═ 3 FIGURING THAT ╥┴═ 3 = ╥┴═ 1 (WHICH IS TRUE ON A
STOCK 128, BUT NOT ON A 256╦ EXPANDED 128!)
┴NYONE WHO WANTS TO GET AHOLD OF THE ┬═OVER SOURCE, OR WHO HAS OTHER
QUESTIONS/COMMENTS/FLAMES CAN CONTACT ME, ╥OBERT ╦NOP, AT THE FOLLOWING
ADDRESSES:
╔NTER╬ET: RKNOP@TYBALT.CALTECH.EDU
╟┼NIE: ╥.╦╬╧╨1
╒.╙. ═AIL: ╥OBERT ╦NOP
123 ╙. ├HESTER #3
╨ASADENA, ├┴ 91106
╓. ╥EFERENCES
[1] ╫ILLIAM ├OLEMAN, 1989: "╔NSIDE ╟┼╧╙ 128" _╘HE_╘RANSACTOR_ 9(4), P. 29.
[2] ╥ICHARD ├URCIO, 1991: "┼XPANDING THE 128 ╨ART ╧NE: 256╦" _╘WIN_├ITIES_128_
#30, P. 7.
[3] ╥ICHARD ├URCIO, 1992: "┼XPANDING THE 128 ╨ART ╘WO: 4 ═ODE 512╦"
_╘WIN_├ITIES_128_ #31, P. 5.
[4] ┬ERKELEY ╙OFTWORKS, 1988: _╘HE_╚ITCHHIKER'S_╟UIDE_╘O_╟EOS_.
[5] ═ICHAEL ╞ARR, 1987: _╘HE_╧FFICAL_╟┼╧╙_╨ROGRAMMER'S_╥EFERENCE_╟UIDE_.
┬ANTAM ┬OOKS, ╬EW ┘ORK/╘ORONTO.
[6] ╠ARRY ╟REENLY ET. AL, 1986: _├OMMODORE_128_╨ROGRAMMER'S_╥EFERENCE_╟UIDE_.
┬ANTAM ┬OOKS, ╬EW ┘ORK/╘ORONTO.
[7] ╧TTIS ╥. ├OWPER, 1986: _═APPING_THE_├OMMODORE_128_. ├OMPUTE! ╨UBLICATIONS,
╟REENSBORO, ╬├.
==============================================================================
─┘╬┴═╔├ ═┼═╧╥┘ ┴╠╠╧├┴╘╔╧╬ ╞╧╥ ╘╚┼ 128: ┬REAKING THE 64╦ ┬ARRIER
BY ├RAIG ┬RUCE (F2RX@JUPITER.SUN.CSD.UNB.CA)
┴LTHOUGH THIS ARTICLE WOULD BE BEST DESCRIBED AS EXTREMELY TECHINICAL, ╔ THINK
THAT IT HAS SOMETHING FOR EVERYONE. ╔T COULD ALSO BE DESCRIBED AS BEING
EXTREMELY LONG.
┬ELOW ╔ HAVE WRITTEN A PROGRAM THAT WILL READ IN THE LINES OF A FILE, SORT
THEM, AND WRITE THEN BACK OUT TO ANOTHER FILE. ┬ECAUSE OF THE NATURE OF THE
PROBLEM, THE EACH LINE OF THE ENTIRE FILE MUST RESIDE IN THE MEMORY OF THE
COMPUTER. ╔ IMPLEMENT AND USE DYNAMIC MEMORY ALLOCATION SUCH THAT THE FILE TO
BE SORTED CAN BE LARGER THAN 64╦, AND ╔ USE A DYNAMIC DATA STRUCTURE SUCH THAT
THE MEMORY IS USED VERY EFFICIENTLY. ╘HE MEMORY ROUTINES WERE EXTRACTED FROM
A TEXT EDITOR CALLED "┌ED-128" WHICH ALSO BREAKS THE 64╦ BARRIER AND CAN EDIT
SOME HUMONGOUS FILES (AND VERY EFFICIENTLY TOO). ┴LTHOUGH IMPLEMENTED FOR THE
├-128, THE DYNAMIC MEMORY SCHEME COULD ALSO BE FAIRLY EASILY (IE. IN A SINGLE
LIFETIME) PORTED TO THE ├-64.
------------------------------------------------------------------------------
1. ╔╬╘╥╧─╒├╘╔╧╬
╚OW MANY OF US ARE SICK AND TIRED OF THE "64╦ LIMIT" THAT MANY PROGRAMS FOR
THE 128 AND 64 SEEM TO HAVE? ═ANY TERMINAL PROGRAMS, TEXT EDITORS, AND EVEN
FILE COPIERS SEEM TO BE AFFLICTED WITH THIS PROBLEM. ┴NOTHER PROBLEM IS THAT
PROGRAMS OFTEN RESERVE LARGE SECTIONS OF MEMORY FOR SPECIFIC PURPOSES (SUCH AS
THE KILL BUFFER OF A TEXT EDITOR) AND CANNOT RECONFIGURE THEMSELVES (VERY
EASILY) FOR DIFFERENT DEMANDS. ╙TILL ANOTHER PROBLEM IS THAT MANY PROGRAMS DO
NOT MAKE USE OF A ╥AM ┼XPANSION ╒NIT (IF YOU ARE FORTUNATE ENOUGH TO HAVE ONE)
TO STORE YOUR VOLUMNOUS USER DATA.
╘HE WAY TO OVERCOME THE LIMITATIONS OF THE 64╦ ARCHITECTURE OF THE ├128 AND
├64 IS TO USE DYNAMICALLY ALLOCATED MEMORY. ╫HAT THIS MEANS IS THAT
INITIALLY, ALL OF THE MEMORY OF THE COMPUTER IS FREE AND WHEN A USER PROGRAM
REQUIRES SOME MEMORY TO STORE USER DATA, IT CALLS A SPECIAL SUBROUTINE THAT
ALLOCATES A GIVEN NUMBER OF BYTES OF MEMORY TO THE PROGRAM TO STORE THE USER
DATA. ┴ND WHEN THE PROGRAM IS FINISHED USING THAT CHUNK OF MEMORY, IT CALLS A
SPECIAL SUBROUTINE TO FREE THE MEMORY CHUNK AND MAKE IT AVAILABLE FOR FUTURE
ALLOCATE REQUESTS.
╧NE COMPLICATION OF THIS MEMORY USAGE SCHEME IS THAT A PROGRAM HAS TO KEEP
TRACK OF WHICH CHUNKS OF MEMORY IT USES FOR WHAT. ╘HIS IS WHERE DYNAMIC DATA
STRUCTURES COME IN. ╘HE MOST IMPORTANT CONCEPT HERE IS A POINTER. ┴ POINTER
IS SIMPLY A VARIABLE THAT STORES THE ADDRESS OF SOME DATA STRUCTURE (IE. SOME
CHUNK OF MEMORY). ╔F WE KNOW THE ADDRESS OF A DATA STRUCTURE, THEN WE CAN
READ IT AND MODIFY IT.
╘O OVERCOME THE PROBLEM OF NOT KNOWING HOW MANY RECORDS WILL NEED TO BE
STORED, RECORDS ARE OFTEN STORED IN LISTS, WHERE EVERY RECORD CONTAINS A
POINTER TO THE NEXT RECORD IN THE LIST, EXCEPT FOR THE LAST ONE, WHICH
CONTAINS A SPECIAL VALUE THAT COULD NOT BE MISTAKEN FOR AN ORDINARY POINTER
(IT IS CALLED THE ╬ULL (OR ╬IL FOR YOU ╨ASCALERS) POINTER). ╘HUS, IF WE KNOW
THE ADDRESS OF THE FIRST RECORD (BY USING A "HEAD POINTER"), THEN WE HAVE
SEQUENTIAL ACCESS TO ALL OF THE RECORDS IN THE LIST. ╔F WE WANT TO ADD OR
DELETE RECORDS FROM THE LIST, THEN WE MUST MODIFY THE OTHER POINTERS SUCH THAT
THE CONSISTENCY OF THE LIST IS MAINTAINED. ╧RGANIZATIONS OTHER THAN SIMPLE
LISTS ARE ALSO POSSIBLE.
╘HE IMPLEMENTATION HERE IS ABLE TO ALLOCATE ╥┴═0 MEMORY FOR STORING USER DATA
RECORDS, AS WELL AS ╥┴═1 MEMORY AND EVEN ╥┼╒ MEMORY. ┴S LONG AS THE
APPLICATION PROGRAM KEEPS TRACK OF THE POINTERS TO ITS RECORDS, LARGE VOLUMES
OF USER DATA CAN BE STORED SINCE IT WILL BE DISTRIBUTED AMONG ALL OF THE
MEMORY THAT IS AVAILABLE FROM BOTH THE INTERNAL MEMORY BANKS AND THE EXTERNAL
MEMORY BANKS, THUS BREAKING THE 64╦ BARRIER.
------------------------------------------------------------------------------
2. ╞╧╥ ╘╚┼ ╬╧╓╔├┼ ╚┴├╦┼╥
┘OU GET A SORTING UTILITY PROGRAM. ╘HIS PROGRAM IMPLEMENTS THE INSERTION SORT
ALGORITHM, SO DON'T EXPECT TO BREAK ANY SPEED RECORDS. ┴LSO, THE WAY THAT
DYNAMIC MEMORY IS IMPLEMENTED HERE IS MORE SUITED FOR LARGE DATA STRUCTURES
THAT WILL ONLY BE ACCESSED SLOWLY AND INFREQUENTLY (SUCH AS THE CURRENT
DOCUMENT IN A TEXT EDITOR); HOWEVER, ╔ WANTED TO COME UP WITH A USEFUL UTILITY
AND ╔ HAVE NEVER HEARD OF A GENERAL FILE SORTER FOR THE 128 OR 64. ╘HE
INSERTION SORT DOES, HOWEVER, LEND ITSELF WELL TO BEING USED WITH DYNAMIC DATA
STRUCTURES IN GENERAL, SINCE YOU DON'T ACTUALLY HAVE TO MOVE ANYTHING; YOU
JUST CHANGE A COUPLE OF POINTERS IN ORDER TO INSERT A LINE (RECORD) BETWEEN
TWO OTHER LINES. ┴LSO, IT TURNS OUT THE THE INSERTION SORT IS QUITE EFFICIENT
IF YOUR INPUT FILE IS ALREADY MOSTLY OR PARTIALLY SORTED.
╘HE SORT UTILITY ITSELF IS COMPLETELY MACHINE LANGUAGE BUT ASSUMES THAT THE
INPUT AND OUTPUT FILES ARE ALREADY OPENED, SO A ┬┴╙╔├ DRIVER PROGRAM IS
REQUIRED TO SET THINGS UP TO AND ALLOW THE USER TO EASILY CHANGE THE SORTING
PARAMETERS. ╙UCH A PROGRAM IS LISTED HERE:
1 I$="INPUTFILE.TXT" : ID=8 : SF=1
2 O$="OUTPUTFILE.TXT" : OD=8
3 :
100 PRINT"LOADING SORT.BIN..."
110 BANK 15
120 BLOAD"SORT.BIN",U(ID)
130 PRINT"SCRATCHING OLD FILE..."
140 SCRATCH(O$),U(OD)
150 PRINT"SORTING..."
160 OPEN1,ID,2,"0:"+I$
170 OPEN2,OD,3,"0:"+O$+",S,W"
180 SYS DEC("1300"),SF
190 CLOSE2
200 CLOSE1
210 PRINT"FINISHED!"
╠INES 1 AND 2 SET UP THE SORTING PARAMETERS: THE INPUT AND OUTPUT FILENAMES,
THE INPUT AND OUTPUT FILE DEVICE NUMBERS, AND THE SORTING FIELD POSITION.
├HANGE THE "SF" VALUE TO THE POSITION OF THE FIRST CHARACTER OF THE KEY
FIELD. ╘HE FIRST POSITION ON THE LINE IS 1 (NOT 0). (╘HIS CORRESPONDS TO
WHAT ┌ED USES FOR COLUMNS). ╙TARTING FROM THAT POSITION, THE REST OF THE LINE
IS USED FOR THE COMPARISON THAT DETERMINES THE ORDER OF THE LINES. ╔F A LINE
IS ENCOUNTERED THAT IS SHORTER THAN THE POSITION OF THE SORTING FIELD, THE KEY
VALUE IS TAKEN TO BE THE ╬ULL ╙TRING (WHICH COMES BEFORE ANY OTHER STRING).
╘HE PROGRAM CONTINUES TO LOAD IN THE MACHINE LANGUAGE (WHICH FITS INTO THE
$1300 SLOT) AND SCRATCH THE OUTPUT FILE IF IT ALREADY EXISTS. ╘HEN THE FILES
ARE OPENED, MACHINE LANGUAGE IS CALLED, AND THE FILES ARE CLOSED AND THE
PROGRAM EXITS. ╫HILE READING THE FILE, THE PROGRAM WILL SPLIT ANY LINES THAT
ARE LONGER THAN 242 CHARACTERS AND TREAT THEM AS MULTIPLE LINES.
╞OR TESTED THE SORT UTILITY, ╔ USED A FILE THAT CONTAINS 1058 LINES OF THE
FOLLOWING FORM:
╥╧╪┼╘╘┼ ═╒╙╘ ╚┴╓┼ ┬┼┼╬ ╠╧╓┼ ┴01-1-01
┴─┴═╙, ┬╥┘┴╬ ╙╒══┼╥ ╧╞ '69 ┴05-1-10
╩╧┼╠, ┬╔╠╠┘ ╨╥┼╙╙╒╥┼ ═11-1-07
┼┴╟╠┼╙ ╬┼╫ ╦╔─ ╔╬ ╘╧╫╬ ╥06-2-04
┼╠┼├╘╥╔├ ╠╔╟╚╘ ╧╥├╚┼╙╘╥┴ ├┴╠╠╔╬╟ ┴═┼╥╔├┴ ╥11-1-05
├╧├╦┬╒╥╬, ┬╥╒├┼ ╫╧╬─┼╥╔╬╟ ╫╚┼╥┼ ╘╚┼ ╠╔╧╬╙ ┴╥┼ ╥14-1-03
┴S YOU MAY GUESS, IT IS A TAPE LIBRARY. ╘HE FILE IS 83╦ IN LENGTH. ╔ SORTED
IT ON BOTH MY 1581 (WITH ╩IFFY─╧╙) AND MY ╥AM╠INK AND THEN ╔ SORTED AGAIN THE
FILE THAT ╔ SORTED IN THE FIRST PLACE. ╘HE RESULTING EXECUTION TIMES ARE AS
FOLLOWS:
╫╔╘╚ ┼╪╨┴╬╙╔╧╬ ═┼═╧╥┘ ╫╔╘╚╧╒╘ ┼╪╨┴╬╙╔╧╬ ═┼═╧╥┘
╥AMLINK REGULAR = 110 SECONDS ╥AMLINK REGULAR = 376 SECONDS
╥AMLINK SORTED = 20 SECONDS ╥AMLINK SORTED = 24 SECONDS
1581 REGULAR = 120 SECONDS 1581 REGULAR = 397 SECONDS
1581 SORTED = 33 SECONDS 1581 SORTED = 55 SECONDS
┘OU'LL NOTE THAT HAVING EXPANSION MEMORY MAKES SORT OPERATE FASTER. ╘HIS IS
BECAUSE THE ╥┼╒ ├ONTROLLER CAN TRANSFER DATA AROUND FASTER THAN THE ├╨╒ CAN.
╘HE EFFECT IS EVEN MORE PRONOUNCED WHEN USING RECORDS LONGER THAN 78-CHARACTER
LINES OF TEXT. ╘HIS IS WHY IT IS SENSIBLE TO USE EXPANSION MEMORY FOR GENERAL
DATA STORAGE AND ACCESSING. ╘HE REASON WHY THE EXECUTION TIMES ARE SO LONG IS
THAT APPROXIMATELY 1058*529/2 = 280,000 "FAR MEMORY" LINE-LENGTH FETCHES HAVE
TO TAKE PLACE, ALONG WITH THAT NUMBER OF "ZPLOAD"S AND STRING COMPARISONS, AND
1058 "MALLOC"S AND "FREE"S. ┴LSO, WE ALL KNOW THAT THE ├OMMODORE FILE READING
AND WRITING MECHANISMS ARE NOT SEVERELY SWIFT.
------------------------------------------------------------------------------
3. ╞╧╥ ╘╚┼ ╔╬╘┼╥═┼─╔┴╘┼ ╚┴├╦┼╥
┘OU GET A DYNAMIC MEMORY ALLOCATION AND USAGE PACKAGE THAT CAN BE INCORPORATED
INTO YOUR OWN PROGRAMS.
3.1. ═┼═╧╥┘ ╨┴├╦┴╟┼ ├┴╠╠╙
╘HE PACKAGE INCLUDES EIGHT SYSTEM CALLS:
STARTUP ()
SHUTDOWN()
ZPLOAD ( [ZP1]=╞AR╨OINTER, .╪=┌P┴DDR, .┘=╠ENGTH )
ZPSTORE ( [ZP1]=╞AR╨OINTER, .╪=┌P┴DDR, .┘=╠ENGTH )
FETCH ( [ZP1]=╞AR╨OINTER, (ZW1)=╥AM0POINTER, .┴┘=╠ENGTH )
STASH ( [ZP1]=╞AR╨OINTER, (ZW1)=╥AM0POINTER, .┴┘=╠ENGTH )
MALLOC ( .┴┘=╠ENGTH ) : [ZP1]=╞AR╨OINTER, .├╙=ERROR
FREE ( [ZP1]=╞AR╨OINTER, .┴┘=╠ENGTH ) : .├╙=ERROR
╘HE "(...)" MEANS INPUT PARAMETERS AND ":" PRECEEDS OUTPUT PARAMETERS. ".╪"
AND ".┘" REFER TO THE PROCESSOR REGISTERS AND ".┴┘" MEANS THE 16-BIT VALUE
WITH THE .┴ REGISTER HOLDING THE LOW BYTE AND THE .┘ REGISTER HOLDING THE HIGH
BYTE. ╫ITH "(ZW1)" ╔ AM REFERING TO THE INDIRECT POINTER IN THE ZERO PAGE
LOCATIONS "ZW1" (LOW BYTE) AND "ZW1+1" (HIGH BYTE) ("ZW" MEANS ZERO PAGE WORD
AND IT IS ASSIGNED TO LOCATIONS $╞┼ TO $╞╞) AND WITH "[ZP1]" ╔ AM REFERING TO
THE THREE BYTE POINTER VALUE IN LOCATIONS "ZP1" (ADDRESS LOW BYTE), "ZP1+1"
(ADDRESS HIGH BYTE), AND "ZP1+2" (BANK NUMBER BYTE) ("ZP" MEANS ZERO PAGE
POINTER AND IT IS ASSIGNED TO ADDRESSES $╞┴ TO $╞├). ╘HIS THREE-BYTE POINTER
IS REFERED TO AS A "╞AR ╨OINTER". ╘HE ".├╙=ERROR" MEANS THAT IF THE ROUTINE
RETURNS WITH THE CARRY FLAG SET, AN ERROR HAS OCCURED. ╘HE ONLY POSSIBLE
ERROR RETURN IN THIS PACKAGE IS IF MALLOC CANNOT FIND ENOUGH CONTIGUOUS FREE
MEMORY TO SATISFY YOUR REQUEST.
┘OU DO NOT ACTUALLY HAVE TO KNOW WHAT THE BANK NUMBERS MEAN SINCE THEY ARE
GENERATED AND USED BY THE PACKAGE AS AN OPAQUE DATA TYPE (PARLEZ-VOUS
═ODULA-2?), BUT HERE IS WHAT THEY MEAN ANYWAY. ┴ VALUE OF $3╞ MEANS INTERNAL
BANK ╥┴═0 AND A VALUE OF $7╞ MEANS INTERNAL BANK ╥┴═1. ╘HIS WORKS OUT
CONVENIENTLY IN THE IMPLEMENTATION, SINCE THESE ARE THE ══╒ CONFIGURATION
REGISTER VALUES FOR THOSE TWO BANKS. ┴ VALUE FROM $80 TO $╞┼ REFERS TO AN
EXPANSION (╥┼╒) MEMORY BANK. $80 MEANS EXPANSION BANK0, $81 BANK1, ETC. ╘HIS
MEANS THAT THE PACKAGE CAN SUPPORT UP TO 8 ═EGS (MINUS 64╦) OF EXPANSION
MEMORY (AND IT DOES). ╘HESE VALUES ARE CONVENIENT TO USE SINCE AFTER LOADING
THE BANK NUMBER INTO A REGISTER, THE ╬EGATIVE FLAG OF THE PROCESSOR WILL BE
SET (USEFUL IF HANDLING EXPANSION MEMORY IS A SPECIAL CASE), AND THIS VALUE
CAN BE PUT DIRECTLY INTO THE ╥┼╒ ├ONTROLLER'S BANK REGISTER. ╔ DON'T THINK
YOU HAVE TO WORRY ABOUT HAVING THE HIGH BIT BE A "1" SINCE IT IS DONE
CONSISTENTLY AND ╔ HAVE NEVER HEARD OF AN ╥┼╒ LARGER THAN 2 ═EGS. ┴ BANK
VALUE OF $╞╞ IS USED TO REPRESENT THE ╬ULL POINTER.
╘HE "STARTUP" ROUTINE INSTALLS THE COMMON CODE, DETERMINES THE SIZE OF YOUR
╥┼╒, AND INITIALIZES THE DYNAMIC MEMORY ALLOCATION MECHANISM. ╔N ORDER FOR
THE PACKAGE TO ACCESS INTERNAL MEMORY BANK ╥┴═1, IT HAS TO CALL A ROUTINE THAT
IS IN MEMORY BELOW ADDRESS $0400. ╙INCE THE PACKAGE STARTS AT $1300, IT HAS
TO COPY A FEW "COMMON CODE" SUBROUTINES INTO LOW MEMORY SUCH THAT IT CAN CALL
THEM LATER. ╘HE COMMON CODE IS INSTALLED AT ADDRESS $0200, THE ┬┴╙╔├ INPUT
BUFFER. ─ON'T OVERWRITE THIS AREA WHILE THE PACKAGE IS IN USE. ╘HE "SNIFF"
ROUTINE IS CALLED TO DETERMINE THE NUMBER OF BANKS THAT YOUR ╥┼╒ HAS. ┌ERO
BANKS MEANS THAT YOU HAVE NO ╥┼╒. ╫HILE SNIFFING, THE PACKAGE OVERWRITES THE
FIRST FOUR BYTES OF EVERY EXISTING EXPANSION BANK (UNLESS YOU LIMIT THE NUMBER
OF EXPANSION BANKS THAT THE PACKAGE IS ALLOWED TO USE). ╘O INITIALIZE THE
DYNAMIC MEMORY ALLOCATION, THE "FREE" ROUTINE IS CALLED FOR ╥┴═0, ╥┴═1, AND
EACH EXPANSION BANK. ╥┴═0 FROM $4000 TO THE TOP OF ┬┴╙╔├ MEMORY ($╞┼╞╞) IS
FREED, ╥┴═1 FROM $0400 TO $╞┼╞╞ IS FREED, AND ALL EXPANSION BANKS ARE FREED
BETWEEN ADDRESSES $0000 TO $╞╞╞7. ╘HUS, IF YOU HAVE NO EXPANSION MEMORY, YOU
GET ABOUT 110╦ FREE AND IF YOU HAVE A 512╦ EXPANDER, YOU GET ABOUT 620╦ FREE.
╘HE "SHUTDOWN" ROUTINE DOESN'T ACTUALLY HAVE VERY MUCH TO DO. ┬ASICALLY, IT
JUST ZEROS OUT THE COMMON CODE. ╔ DID THIS SO IF YOU CALLED THE SORT ROUTINE
FROM ┬┴╙╔├ DIRECT INPUT MODE, YOU WOULD NOT GET A "SYNTAX ERROR" FROM ┬┴╙╔├
TRYING TO INTERPRET THE GARBAGE LEFT BEHIND. ╬OW, WHEN ┬┴╙╔├ ENCOUNTERS A
ZERO, IT STOPS INTERPRETING.
╘HE "ZPLOAD" ROUTINE WILL LOAD THE GIVEN NUMBER OF BYTES INTO ZERO PAGE
STARTING AT THE GIVEN ZERO PAGE ADDRESS, FROM ANY FAR POINTER ADDRESS. ╔T
DOESN'T MATTER WHETHER THE FAR ADDRESS IS IN INTERNAL OR EXPANSION MEMORY; THE
OPERATION IS THE SAME. ╘HIS IS THE LEVEL OF SOFTWARE THAT MAKES ACCESSING THE
DIFFERENT TYPES OF MEMORY TRANSPARENT TO THE USER. ╘O LOAD FROM ╥┴═0, TRUE
╥┴═0 IS SWITCHED INTO CONTEXT (DID ╔ MENTION THAT THE PACKAGE IS MEANT TO
EXECUTE WITH ══╒ CONFIGURATION $0┼ IN CONTEXT - THIS CONFIGURATION GIVES ╥┴═0
FROM $0000 TO $┬╞╞╞, THE KERNEL ╥╧═ FROM $├000 TO $╞╞╞╞ AND THE ╔/╧ SPACE ON
TOP OF THE KERNEL ╥╧═ FROM $─000 TO $─╞╞╞ - ╔ CALL THIS THE ╙┘╙ OR ╙┘╙0 BANK)
AND THE TRANSFER IS DONE WITH A LOOP. ╞OR A ZPLOAD FROM ╥┴═1, A COMMON CODE
ROUTINE IS CALLED THAT SWITCHES ╥┴═1 INTO CONTEXT, COPIES IN A LOOP, AND THEN
SWITCHES BACK TO ╙┘╙0. ╞OR AN EXPANSION MEMORY POINTER, THE ╥┼╒ ├ONTROLLER
REGISTERS ARE SET UP AND THE TRANSFER IS PERFORMED. ╘HE PACKAGE WILL WORK
WITH WHATEVER ┌ERO ╨AGE IS IN CONTEXT (WITH ══╒ REGISTER $─507), SINCE IT IS
CONVENIENT TO USE YOUR OWN ZERO PAGE IN YOUR PROGRAMS. ╞OR TRANSFERS OF LESS
THAN ABOUT 16 BYTES, INTERNAL MEMORY IS FASTER, AND FOR LONGER TRANSFERS,
EXPANSION MEMORY TURNS OUT TO BE FASTER. ╞OR REALLY LONG TRANSFERS (SAY, 80
BYTES), USING THE EXPANSION MEMORY IS ═╒├╚ FASTER (A MARGINAL COST OF ONE
MICROSECOND PER BYTE AS OPPOSED TO NINE). ╘HE "[ZP1]" PARAMETER IS UNALTERED
BY THIS CALL, BUT THE REGISTER VALUES ARE QUITE CHANGED. ╘HE "(ZW1)"
PARAMETER AREA IS ALSO LEFT UNTOUCHED.
╘HE "ZPSTORE" ROUTINE WORKS THE SAME AS "ZPLOAD" EXCEPT IT STORES TO THE FAR
MEMORY FROM ZERO PAGE.
╘HE "FETCH" ROUTINE FETCHES THE GIVEN NUMBER OF BYTES FROM A FAR ADDRESS INTO
THE ╥┴═0 BANK (NOT ╙┘╙0) AT THE GIVEN ADDRESS. ╒NLIKE THE ZERO PAGE LOAD
ROUTINE, YOU CAN TRANSFER UP TO 64╦ OF MEMORY WITH THIS ROUTINE. ┴GAIN, THE
TYPE OF MEMORY TO BE FETCHED IS TRANSPARENT TO THE USER. ╞OR AN INTERNAL
MEMORY FETCH, THE TRANSFERS ARE PERFORMED IN 256 BYTE CHUNKS. ╘HIS MAKES THE
IMPLEMENTATION EASIER. ╞OR EACH BYTE TRANSFERRED FROM ╥┴═1, ╥┴═1 IS SWITCHED
IN AND THEN ╥┴═0 IS SWITCHED IN, SO THE TRANSFER IS NOT EXTREMELY EFFICIENT.
╞OR THE EXPANSION MEMORY, THE ╥┼╒ ├ONTROLLER IS SET UP AND THEN THE ENTIRE
TRANSFER (UP TO 64╦) IS PERFORMED AT A RATE OF 1 ═EG/SECOND. ╘HIS IS
CONSIDERABLY FASTER THAN INTERNAL MEMORY FETCHING. ╘HIS ROUTINE HANDLES A
TRANSFER LENGTH OF 0 BYTES PROPERLY. ╘HE "ZP1" AND "ZW1" PARAMETERS ARE
RETURNED UNALTERED, BUT AGAIN, THE REGISTERS ARE SMASHED.
╘HE "STASH" ROUTINE OPERATES THE SAME AS FETCH, EXCEPT THAT THE DATA IS
TRANSFERRED FROM THE NEAR ("ZW1") ADDRESS TO THE FAR ("ZP1") ADDRESS.
╘HE "MALLOC" ROUTINE ATTEMPTS TO FIND A CHUNK OF CONTIGUOUS MEMORY OF THE
GIVEN LENGTH TO ALLOCATE TO YOU. ╔F IT CAN FIND ONE, IT RETURNS THE FAR
POINTER TO IT IN THE "[ZP1]" PARAMETER. ╔F IT CANNOT FIND ONE, IT RETURNS
WITH THE CARRY FLAG SET. ╘HIS ROUTINE CLOBBERS THE REGISTERS.
╘HE "FREE" ROUTINE RETURNS TO THE POOL OF FREE MEMORY THE CHUNK OF MEMORY
SPECIFIED BY THE FAR POINTER AND LENGTH PARAMETERS. ╘HIS ROUTINE CLOBBERS THE
"[ZP1]" PARAMETER AND THE REGISTERS. ╘HE CARRY FLAG IS ALWAYS CLEARED UPON
RETURN, SINCE THE ROUTINE DOES NOT (CURRENTLY) CHECK FOR ANY ERRORS.
3.2. ═┼═╧╥┘ ┴╠╠╧├┴╘┼ ┴╬─ ╞╥┼┼
╘HE MALLOC AND FREE ROUTINES MAINTAIN A LINKED LIST OF FREE MEMORY CHUNKS. ┴
FREE MEMORY CHUNK IS DESCRIBED BY A FIVE BYTE STRUCTURE THAT IS AT THE
BEGINNING OF THE CHUNK. ╘HE FIRST THREE BYTES ARE A FAR POINTER TO THE NEXT
FREE MEMORY CHUNK AND THE FOLLOWING TWO BYTES GIVE THE TOTAL LENGTH OF THE
CHUNK. ╘HE STRUCTURE IS THUS:
+----------+----------+----------+----------+----------+---...
▄ ╬EXT ▄ ╬EXT ▄ ╬EXT ▄ ├HUNK ▄ ├HUNK ▄
▄ CHUNK ▄ CHUNK ▄ CHUNK ▄ LENGTH ▄ LENGTH ▄ GARBAGE
▄ LOW ADDR ▄ HIGH ADDR▄ BANK NUM ▄ LOW ▄ HIGH ▄
+----------+----------+----------+----------+----------+---...
CHUNK+0 CHUNK+1 CHUNK+2 CHUNK+3 CHUNK+4
┴LL OF THE FREE (AND ALLOCATED) MEMORY CHUNKS ARE ALWAYS ALIGNED ON AN EIGHT
BYTE BOUNDARY. ╘HIS GUARANTEES THAT NO MATTER WHAT HAPPENS, THERE WILL ALWAYS
BE AT LEAST EIGHT BYTES AVAILABLE IN EACH FREE MEMORY CHUNK TO HOLD THE FREE
CHUNK DESCRIPTOR INFORMATION. ╘HUS, IF YOU WERE TO MAKE A REQUEST FOR THREE
BYTES, THE SYSTEM WOULD GIVE YOU EIGHT, AND WHEN YOU REQUEST TO FREE THOSE
THREE BYTES, THE SYSTEM WOULD AUTOMATICALLY FREE EIGHT. ╘HIS CAN LEAD TO SOME
SOME WASTED SPACE WHEN USING SMALL STRUCTURES.
╘HE MEMORY CHUNKS ARE KEPT IN ORDER OF "INCREASING" ADDRESS. ╔ SAY
"INCREASING" BECAUSE WHILE THE CHUNKS WITHIN A BANK ARE IN INCREASING ADDRESS
ORDER, THE SYSTEM CONSIDERS BANK NUMBER $87 (EXPANSION BANK 7) TO BE LOWER
THAN BANK NUMBER $3╞ (╥┴═0). ╘HIS ANOMOLY MAKES THE SYSTEM ALLOCATE ITS
EXTERNAL MEMORY BEFORE ALLOCATING INTERNAL MEMORY. ╘HIS IS GOOD SINCE
EXTERNAL MEMORY GENERALLY WORKS FASTER THAN INTERNAL MEMORY.
╘HIS MEMORY IS ALLOCATED FIRST SINCE THE MALLOC ROUTINE USES A FIRST-FIND
ALGORITHM FOR SEARCHING FOR A SUFFICIENT FREE MEMORY CHUNK. ╔T STOPS
SEARCHING WHEN IT FINDS A FREE MEMORY CHUNK LARGE ENOUGH TO SATISFY THE USER'S
REQUEST. ╔F THE FREE CHUNK IS EXACTLY THE SAME SIZE AS THE REQUEST, THE FREE
CHUNK IS UNLINKED FROM THE FREE CHUNK LIST AND THE POINTER IS RETURNED. ╔F
THE FREE CHUNK IS LARGER THAN THE REQUESTED SIZE, IT IS SPLIT UP. ┴ POINTER
TO THE TOP ╬ BYTES OF THE CHUNK IS RETURED TO THE USER AND THE SIZE OF THE
FREE CHUNK IS REDUCED BY ╬. ╘HE MEMORY IS ALLOCATED FROM THE TOP OF THE CHUNK
MAKE IT SO NO LINKING AND UNLINKING HAS TO TAKE PLACE IN THIS CASE.
╘HE FREE ROUTINE IS MORE COMPLICATED THAN THE ALLOCATE ROUTINE SINCE FREE HAS
TO DEAL WITH MORE CASES. ╞REE HAS TO SEARCH THROUGH THE LINKED LIST OF FREE
MEMORY CHUNKS TO FIND THE TWO CHUNKS THAT STRADDLE THE CHUNK TO BE FREED.
╞REE ATTEMPTS TO COALESCE (MERGE) THE NEW CHUNK WITH THE PREVIOUS CHUNK AND
WITH THE NEXT CHUNK IN ORDER TO END UP WITH THE LARGEST FREE CHUNKS THAT IT
CAN UNDER THE CIRCUMSTANCES. ╠ARGE FREE CHUNKS ARE GOOD SINCE THEY CAN BE
USED FOR LARGER REQUESTS. ╘WO CHUNKS CAN BE COALESCED IF THEY ARE
SIDE-BY-SIDE IN MEMORY (ZERO BYTES APART) AND ON THE SAME BANK. ╘O COALESCE
THEM, THE SIZE OF THE FIRST ONE IS INCREASED BY THE SIZE OF THE SECOND ONE AND
THE POINTER TO THE SECOND ONE IS FORGOTTEN.
╬OTE THAT THIS SCHEME WORKS DIFFERENTLY FROM THE DYNAMIC ALLOCATION SCHEME
THAT ┬┴╙╔├ USES FOR ITS STRINGS. ┬┴╙╔├ DOES NOT ATTEMPT TO COALESCE TOGETHER
(OR EVEN RE-USE) FREED CHUNKS; IT RELIES UPON GARBAGE COLLECTING TO GET RID OF
THE FREE CHUNKS. ╘HE SCHEME IMPLEMENTED HERE IS MORE STATIC (INTERESTING WORD
TO CHOOSE) IN THAT ONCE YOU ARE ALLOCATED A CHUNK, THAT CHUNK IS PINNED TO
THAT ADDRESS AND WILL NEVER MOVE. ╘HIS STATIC ORGANIZATION CAN LEAD TO THE
PROBLEM OF MEMORY FRAGMENTATION, WHERE LOTS OF MEMORY CAN BE FREE BUT IS IN
UN-COALESCABLE CHUNKS THAT ARE TOO SMALL TO BE USEFUL. ╧H WELL. ╔ DON'T
THINK THAT IT IS REALLY A PROBLEM FOR STORING LINES OF TEXT AS INDIVIDUAL
RECORDS, AND IT IS NO PROBLEM AT ALL FOR A PROGRAM THAT ALWAYS USES FIXED SIZE
RECORDS.
3.3. ╘╚┼ ╙╧╥╘ ╒╘╔╠╔╘┘
╘HE WAY THAT THE SORT UTILITY MAKES FULL USE OF THE CAPABILITES OF THE
PACKAGE. ╞IRST IT READS IN THE INPUT FILE ONE LINE AT A TIME AND STORES THE
LINES IN A LINKED LIST AS INDIVIDUAL RECORDS OF THE FORM:
+--------+--------+--------+--------+-------...-----+--------+
▄ ╬EXT ▄ ╬EXT ▄ ╬EXT ▄ ╘OTAL ▄ ▄ ▄
▄ LINE ▄ LINE ▄ LINE ▄ RECORD ▄ CHARACTERS ▄ .BYTE ▄
▄ PTR ▄ PTR ▄ PTR ▄ LENGTH ▄ OF THE LINE ▄ $00 ▄
▄ LOW ▄ HIGH ▄ BANK ▄ ▄ ▄ ▄
+--------+--------+--------+--------+-------...-----+--------+
LINE+0 LINE+1 LINE+2 LINE+3 LINE+4 LINE+?
╬OTE THAT THESE ARE VARIABLE LENGTH RECORDS; EACH RECORD IS ONLY AS LONG AS IT
HAS TO BE. ╘HE TOTAL RECORD LENGTH IS STORED AT THE FRONT OF THE RECORD. ╔N
ORDER TO READ A LINE INTO A PROCESSING BUFFER, A "ZPLOAD" IS DONE THAT READS
THE FIRST FOUR BYTES OF THE RECORD IN ORDER TO GET THE LENGTH OF THE RECORD.
╘HEN THE ENTIRE RECORD CAN BE FETCHED SINCE ITS LENGTH IS KNOWN AT THAT TIME.
┼ACH RECORD ENDS WITH A $00 BYTE TO SIMPLIFY THE STRING COMPARISON
SUBROUTINE.
╘HE LINE LIST IS MAINTAINED IN ALPHABETICAL ORDER (ACTUALLY, REVERSE
ALPHABETICAL ORDER; BELOW). ╫HEN A NEW LINE IS READ IN FROM THE INPUT FILE,
THE LINE LIST IS SEARCHED FOR THE TWO OTHER LINES WHOSE VALUES STRADDLE THE
VALUE OF THE NEW LINE. ╘HE LINE IS THEN LINKED IN AT THAT POSITION IN THE
LIST. ╬O OTHER LINES HAVE TO BE MOVED AROUND SINCE POINTERS ARE USED TO
MAINTAIN THE ORDER OF THE LIST. ╔N ORDER FOR A LINE ALREADY IN THE LIST TO BE
COMPARED WITH THE NEW LINE, THE OLD LINE HAS TO BE FETCHED FROM FAR MEMORY
(USING THE ZPLOAD + FETCH SCHEME ABOVE) INTO A WORK BUFFER IN THE ╙┘╙0 BANK.
╧N AVERAGE, HALF OF THE EXISTING LIST WILL HAVE TO BE SEARCHED IN THIS WAY IN
ORDER TO FIND THE CORRECT SPOT TO INSERT THE NEW LINE.
┴FTER THE POSITION FOR THE NEW LINE IS FOUND, SPACE FOR THE LINE IS ALLOCATED
BY CALLING "MALLOC" AND THEN THE DATA IS STORED FROM THE WORK BUFFER IT WAS
READ INTO TO FAR MEMORY. ╘HE ZPLOAD AND ZPSTORE ROUTINES ARE USED TO MODIFY
THE POINTERS TO LINK IN THE NEW LINE. ┴ NUMBER OF POINTER MANIPULATIONS ARE
ALSO REQUIRED ON THE ZERO PAGE VARIALBLES.
╔F THE LINE LIST WAS GENERATED IN FORWARD ALPHABETIC ORDER, THEN THE UTILITY
WOULD ACHIEVE ITS ╫╧╥╙╘ PERFORMANCE WHEN THE INPUT FILE WAS ALREADY MOSTLY OR
PARTIALLY SORTED. ╘HIS IS BECAUSE WHEN EACH LINE IS READ, IF IT COMES AFTER
MOST OR ALL OF THE OTHER LINES, THE MOST OR ALL OF THE LINE LIST WOULD HAVE TO
BE SEARCHED TO FIND THE FINAL RESTING POSITION FOR THE NEW LINE. ╘HIS WOULD
BE UNACCEPTABLE AND EXTREMELY WASTEFUL. ┴ BETTER SCHEME IS TO GENERATE THE
LINE LIST IN REVERSE ALPHABETIC ORDER. ╘HEN, WHEN A "HIGHER VALUED" LINE IS
READ IN, ITS CORRECT POSITION WOULD BE AT OR NEAR THE TOP OF THE LIST, SO ONLY
IT WOULD ONLY HAVE TO BE COMPARED AGAINST A FEW OF THE LINES ALREADY ON THE
LIST. ╔N THE CASE OF AN INPUT FILE THAT IS ALREADY IN PRETTY MUCH RANDOM
ORDER, IT MAKES NO DIFFERENCE WHETHER THE LIST IS IN FORWARD OR REVERSE
ORDER.
╙INCE THE LIST IS GENERATED IN REVERSE ORDER, IT MUST BE REVERESED AGAIN
BEFORE WRITING IT TO THE OUTPUT FILE, SINCE THE USER WOULD WANT IT TO BE IN
FORWARD ORDER (AND SINCE THIS IS THE ORDER THAT CAN BE MOST EASILY SORTED
AGAIN LATER). ┴ CLEVER LITTLE SUBROUTINE IS CALLED THAT REVERSES THE ORDER OF
THE LIST. ╔T ONLY HAS TO MAKE USE OF ZPLOAD AND ZPSTORE TO READ/CHANGE THE
FIRST FEW BYTES OF EACH RECORD, SINCE IT IS NOT CONCERNED WITH THE DATA
CONTENTS OF EACH RECORD.
┴LTHOUGH THIS IS NOT STRICTLY NECESSARY, ALL OF THE RECORDS IN THE LINE LIST
ARE FREED BEFORE THE SORT UTILITIY EXITS. ╘HIS IS A GOOD PRACTICE, AND WOULD
NECESSARY IF THE PROGRAM WERE TO CONTINUE TO DO USEFUL WORK AFTER WRITING THE
SORTED FILE TO OUTPUT. ┴ POINTER IS STEPPED THROUGH THE LIST (STARTING FROM
THE HEAD POINTER) AND THE SPACE FOR EACH LINE IS DEALLOCATED BY CALLING FREE,
AFTER DETERMINING THE SIZE OF THE RECORD BY READING THE FIRST FEW BYTES OF
IT. ╙INCE THE LIST WILL BE IN (PRETTY MUCH) RANDOM ORDER (OF ADDRESSES), THE
DEALLOCATION MECHANISM DOES NOT ACHIEVE ITS BEST PERFORMANCE.
┴ CONVENIENT JUMP TABLE IS SET UP AT THE START OF THE CODE TO MAKE IT EASIER
FOR YOU TO LINK YOUR OWN PROGRAMS TO THE PACKAGE. ═AKE SURE THAT ══╒
CONFIGURATION VALUE $0┼ IS IN EFFECT BEFORE CALLING ANY OF THE ROUTINES. ┘OU
MAY HAVE TO MUCK WITH THE CODE A LITTLE BIT TO GET IT TO WORK FOR YOU.
------------------------------------------------------------------------------
4. ╞╧╥ ╘╚┼ ┼╪╨┼╥╘ ╚┴├╦┼╥
┘OU GET TO SEE THE CODE THAT ACTUALLY IMPLEMENTS THE MEMORY PACKAGE AND THE
SORT UTILITY. ╔ HAVE IT HERE IN A SPECIAL FORM; EACH CODE LINE IS PRECEEDED
BY A FEW SPECIAL CHARACTERS AND THE LINE NUMBER. ╘HE LINE NUMBER IS THERE TO
ALLOW ME TO REFER TO SPECIFIC LINES, AND THE SPECIAL CHARACTERS ARE THERE TO
ALLOW YOU TO EASILY EXTRACT THE ASSEMBLER CODE FROM THE REST OF THIS MAGAZINE
(AND ALL OF MY UGLY COMMENTS). ╧N A ╒NIX SYSTEM, ALL YOU HAVE TO DO IS
EXECUTE THE FOLLOWING COMMAND LINE (SUBSTITUTE FILENAMES AS APPROPRIATE):
GREP '^\.%....\!' ╚ACK2 ▄ SED 'S/^.%....\!..//' ▄ SED 'S/.%....\!//' >SORT.ASM
─ONTCHA JUST LOVE THOSE ╒NIX COMMANDS! ╚ERE IS THE ASSEMBLER CODE:
.%0001! ;╙ORT UTILITY USING DYNAMIC MEMORY ALLOCATION WITH EXPANDED MEMORY
.%0002! ;WRITTEN 92/04/22 BY ├RAIG ┬RUCE FOR ├= ╚ACKING ╬ET ═AGAZINE
.%0003! ;--------------------------------------------------------------------
╘HIS PROGRAM IS WRITTEN FOR THE ┬UDDY ASSEMBLER. ╠IKE MOST ASSEMBLERS, IT
NEEDS A FEW DIRECTIVES TO START OFF, SO HERE THEY ARE. ╬OTE THAT MY COMMENTS
COME ┬┼╞╧╥┼ THE SECTION OF CODE THAT ╔ AM COMMENTING ON.
.%0004! .MEM
.%0005! .BANK 15
.%0006! .ORG $1300
.%0007!
.%0008! ;*** GLOBAL DECLARATIONS
.%0009!
╚ERE ARE THE ZERO PAGE LOCATIONS THAT THE PACKAGE USES FOR ITS OWN PURPOSES.
╔ STUCK THE SYS╫ORK VARIABLE OVER THE ┬┴╙╔├ GRAPHICS COMMAND PARAMETERS SINCE
IT SEEMS LIKE A GOOD PLACE. ╔T REQUIRES 16 BYTES AND IS USED BY MOST OF THE
ROUTINES FOR TEMPORARY STORAGE. "TEMP1" IS USED FOR "VERY" TEMPORARY
STORAGE.
.%0010! ZP1 = $FA
.%0011! TEMP1 = $FD
.%0012! ZW1 = $FE
.%0013! SYS╫ORK = $80 ;16-BYTE BLOCK
.%0014!
╘HESE ARE THE NON-ZERO PAGE STORAGE LOCATIONS. ╘HE COMMON CODE BUFFER PRETTY
MUCH HAS TO BE AT $200 SINCE THAT IS (ABOUT) THE ONLY FREE SECTION OF MEMORY
BELOW ADDRESS $0400 (IN THE COMMON MEMORY RANGE).
.%0015! COM├ODE┬UFFER = $200
.%0016! WORK┬UFFER = $B00
.%0017!
╘HESE ARE THE ══╒ CONFIGURATION REGISTER VALUES AND SOME IMPORTANT ╔/╧
ADDRESSES.
.%0018! BK╙YS = $0E
.%0019! BK╦ERNEL = $00
.%0020! BK╙ELECT = $FF00
.%0021! BK╙ELECT╥AM0 = $FF01
.%0022! BK╙ELECT╥AM1 = $FF02
.%0023! BK╥AM0 = $3F
.%0024! BK╥AM1 = $7F
.%0025! BK┼XP0 = $80
.%0026! BK╬ULL = $FF
.%0027! ZP╙ELECT = $D507
.%0028! REU = $DF00
.%0029! VIC = $D000
.%0030!
.%0031! ERR╔NSUFFICIENT═EMORY = 1
.%0032!
.%0033! ;*** JUMP TO MAIN ROUTINE
.%0034!
.%0035! JMP MAIN
.%0036!
.%0037! ;*** JUMP TABLE
.%0038!
╚ERE'S THAT JUMP TABLE.
.%0039! STARTUP JMP INTERN╙TARTUP
.%0040! SHUTDOWN JMP INTERN╙HUTDOWN
.%0041! ZPLOAD JMP INTERN┌P╠OAD
.%0042! ZPSTORE JMP INTERN┌P╙TORE
.%0043! FETCH JMP INTERN╥AM0╞ETCH
.%0044! STASH JMP INTERN╥AM0╙TASH
.%0045! MALLOC JMP INTERN┴LLOC
.%0046! FREE JMP INTERN╞REE
.%0047!
.%0048! ;*** STORAGE
.%0049!
╚ERE ARE SOME USEFUL STORAGE LOCATIONS. "ERRNO" CONTAINS THE CODE FOR THE
ERROR ENCOUNTERED IN A ROUTINE IF THE ROUTINE EXITS WITH THE CARRY FLAG SET
(AND IT IS SUPPOSED TO BE CLEARED FOR ╧╦). "N┼XP┬ANKS" GIVES THE NUMBER OF
EXPANSION MEMORY BANKS, AND "FREE═EMORY" GIVES THE NUMBER OF BYTES CURRENTLY
FREE IN THE SYSTEM. ┬OTH OF THESE ARE USEFUL STATUS VALUES AND CAN BE READ
DIRECTLY.
.%0050! ERRNO .BUF 1
.%0051! N┼XP┬ANKS .BUF 1
.%0052! MALLOC╚EAD .BUF 3
.%0053! FREE═EMORY .BUF 3
.%0054!
.%0055! ;***STARTUP
.%0056!
╘HIS ROUTINE GETS THE BALL ROLLING. ╔T CLEARS THE STATUS REGISTER IN CASE YOU
START UP THE SYSTEM WITH THE DECIMAL MODE FLAG SET OR INTERRUPTS DISABLED.
.%0057! INTERN╙TARTUP = *
.%0058! LDA #0
.%0059! PHA
.%0060! PLP
.%0061! LDA #BK╙YS
.%0062! STA BK╙ELECT
.%0063! JSR INSTALL├OMMON├ODE
.%0064! JSR SNIFF╥┼╒
.%0065! JSR INIT─YNAMIC═EMORY
.%0066! RTS
.%0067!
┴ND THIS ROUTINE STOPS THE BALL FROM ROLLING. ╔ FILL THE ┬┴╙╔├ COMMAND LINE
BUFFER WITH ZEROS TO STOP THAT SYNTAX ERROR THING.
.%0068! INTERN╙HUTDOWN = *
.%0069! LDX #0
.%0070! LDA #0
.%0071! - STA $200,X
.%0072! INX
.%0073! CPX #COM├ODE┼ND-COM├ODE╙TART
.%0074! BNE -
.%0075! LDA #BK╦ERNEL
.%0076! STA BK╙ELECT
.%0077! RTS
.%0078!
.%0079! ;***INSTALL COMMON CODE
.%0080!
╘HIS ROUTINE COPIES THE COMMON CODE SUBROUTINES INTO THE COMMON CODE BUFFER
(AT $0200).
.%0081! INSTALL├OMMON├ODE = *
.%0082! LDX #0
.%0083! - LDA COM├ODE╙TART,X
.%0084! STA COM├ODE┬UFFER,X
.%0085! INX
.%0086! CPX #COM├ODE┼ND-COM├ODE╙TART
.%0087! BCC -
.%0088! RTS
.%0089!
.%0090! ;--------------------------------------------------------------------
.%0091! ;***COMMON CODE
.%0092!
┴ND THIS IS THE COMMON CODE. ╔T CONTAINS FOUR SUBROUTINES FOR ACCESSING ╥┴═1
(AND THE ZERO PAGE ROUTINES ARE USED FOR ╥┴═0 AS WELL).
.%0093! COM├ODE╙TART = *
.%0094!
╙ELECTS THE ══╒ CONFIGURATION ACCORDING TO THE BANK NUMBER AND COPIES THE
NUMBER OF BYTES REQUIRED FOR A ZPLOAD. ╔T EXITS BY RESTORING THE ╙┘╙ BANK.
╘HIS IS USED ONLY FOR INTERNAL MEMORY ZPLOADS.
.%0095! COM┌P╠OAD = *
.%0096! LDA ZP1+2
.%0097! STA BK╙ELECT
.%0098! STY TEMP1
.%0099! LDY #0
.%0100! - LDA (ZP1),Y
.%0101! STA 0,X
.%0102! INX
.%0103! INY
.%0104! CPY TEMP1
.%0105! BCC -
.%0106! LDA #BK╙YS
.%0107! STA BK╙ELECT
.%0108! RTS
.%0109!
╨RETTY MUCH THE SAME AS ZPLOAD.
.%0110! COM┌P╙TORE = *
.%0111! LDA ZP1+2
.%0112! STA BK╙ELECT
.%0113! STY TEMP1
.%0114! LDY #0
.%0115! - LDA 0,X
.%0116! STA (ZP1),Y
.%0117! INX
.%0118! INY
.%0119! CPY TEMP1
.%0120! BCC -
.%0121! LDA #BK╙YS
.%0122! STA BK╙ELECT
.%0123! RTS
.%0124!
┴S THE NAME SUGGESTS, THIS COPIES FROM ╥┴═1 TO ╥┴═0. ╧NLY .┘ NUMBER OF BYTES
ARE COPIED, AND IF .┘=0, 256 BYTES ARE COPIED. ┘OU'LL NOTICE THAT THE ══╒
CONFIGURATIONS ARE SWITCHED BETWEEN FOR EVERY BYTE COPIED. ╘HIS IS NOT THE
MOST EFFICIENT SCHEME, BUT IT SUFFICES. ╘HE ══╒ PRECONFIGURATION REGISTERS
ARE USED AND THE VALUE THAT ┬┴╙╔├ PUT IN THEM ARE ASSUMED TO STILL BE THERE.
.%0125! COM├OPY╥AM1╘O╥AM0 = *
.%0126! DEY
.%0127! BEQ +
.%0128! - STA BK╙ELECT╥AM1
.%0129! LDA (ZP1),Y
.%0130! STA BK╙ELECT╥AM0
.%0131! STA (ZW1),Y
.%0132! DEY
.%0133! BNE -
.%0134! + STA BK╙ELECT╥AM1
.%0135! LDA (ZP1),Y
.%0136! STA BK╙ELECT╥AM0
.%0137! STA (ZW1),Y
.%0138! LDA #BK╙YS
.%0139! STA BK╙ELECT
.%0140! RTS
.%0141!
╘HE OPPOSITE DIRECTION.
.%0142! COM├OPY╥AM0╘O╥AM1 = *
.%0143! DEY
.%0144! BEQ +
.%0145! - STA BK╙ELECT╥AM0
.%0146! LDA (ZW1),Y
.%0147! STA BK╙ELECT╥AM1
.%0148! STA (ZP1),Y
.%0149! DEY
.%0150! BNE -
.%0151! + STA BK╙ELECT╥AM0
.%0152! LDA (ZW1),Y
.%0153! STA BK╙ELECT╥AM1
.%0154! STA (ZP1),Y
.%0155! LDA #BK╙YS
.%0156! STA BK╙ELECT
.%0157! RTS
.%0158!
╘HE END OF THE COMMON CODE. ╘HE LENGTH OF THE COMMON CODE IS DETERMINED BY
SUBTRACTING THE END ADDRESS FROM THE START ADDRESS.
.%0159! COM├ODE┼ND = *
.%0160!
.%0161! ;--------------------------------------------------------------------
.%0162! ;*** ZPLOAD( [ZP1]=╙OURCE, .╪=┌P─EST, .┘=╠ENGTH )
.%0163!
╘HE ACTUAL ZPLOAD ROUTINE. ╔T DISPATCHES TO THE COMMON CODE ROUTINE IF
INTERNAL MEMORY IS SPECIFIED BY THE FAR POINTER, OR FALLS THROUGH TO ╥┼╒ CODE
IF EXPANSION MEMORY IS SPECIFIED.
.%0164! INTERN┌P╠OAD = *
.%0165! LDA ZP1+2
.%0166! BMI +
.%0167! JMP COM┌P╠OAD-COM├ODE╙TART+COM├ODE┬UFFER
.%0168! + STY REU+7
.%0169! LDY #$91
.%0170!
╙ETS UP THE ╥┼╒ ├ONTROLLER REGISTERS FOR THE PARAMETERS OF THE TRANSFER. ╬OTE
THAT THE VALUE OF THE ZERO PAGE ADDRESS IS NOT ASSUMED TO BE ABSOLUTE $0000
BUT IS TAKEN FROM THE ZERO PAGE SELECTION REGISTER OF THE ══╒. ╘HE ╥┼╒
├ONTROLLER DOES NOT USE THE ══╒ FOR DECODING ZERO PAGE AND STACK PAGE
ADDRESSES; IT ACCESSES THE ABSOLUTE MEMORY DIRECTLY.
.%0171! ZERO╨AGE╥EU╧P = *
.%0172! STA REU+6
.%0173! STX REU+2
.%0174! LDA ZP╙ELECT
.%0175! STA REU+3
.%0176! LDA ZP1
.%0177! STA REU+4
.%0178! LDA ZP1+1
.%0179! STA REU+5
.%0180! LDA #0
.%0181! STA REU+8
╚ERE THE SYSTEM CLOCK SPEED IS PUT INTO ╙LOW MODE WHILE THE TRANSFER OCCURS
AND IS THEN RESTORED. ╘HIS IS NECESSARY.
.%0182! LDA VIC+$30
.%0183! LDX #$00
.%0184! STX VIC+$30
.%0185! STY REU+1
.%0186! STA VIC+$30
.%0187! RTS
.%0188!
.%0189! ;*** ZPSTORE( .╪=┌P╙OURCE, [ZP1]=─EST, .┘=╠ENGTH )
.%0190!
╨RETTY MUCH THE SAME AS THE ZPLOAD ROUTINE, EXCEPT THAT A COMMAND CODE FOR THE
╥┼╒ ├ONTROLLER IS DIFFERENT (SPECIFYING AN INTERNAL TO EXPANSION MEMORY
TRANSFER). ╘HE ╥┼╒ CODE IN THE ZPLOAD ROUTINE IS CALLED.
.%0191! INTERN┌P╙TORE = *
.%0192! LDA ZP1+2
.%0193! BMI +
.%0194! JMP COM┌P╙TORE-COM├ODE╙TART+COM├ODE┬UFFER
.%0195! + STY REU+7
.%0196! LDY #$90
.%0197! JMP ZERO╨AGE╥EU╧P
.%0198!
.%0199! ;--------------------------------------------------------------------